package com.example.base.tools.upgrade

import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import okhttp3.ResponseBody
import java.io.BufferedInputStream
import java.io.File
import java.io.RandomAccessFile

/**  文件写入工具类  **/
object FileWriteTool {

    /**  将返回的内容写入到磁盘文件中  **/
    suspend fun writeToDisk(
        responseBody: ResponseBody,
        downloadInfo: DownloadInfo,
        listener: StatusListener.() -> Unit
    ) = withContext(Dispatchers.IO) {
        val statusListener = StatusListener()
        // 此时说明文件已下载好了, 直接跳转安装即可
        // TODO 下载完成回调
        if (getFileStartPoint(
                downloadInfo.apkSavePath,
                downloadInfo.fileName
            ) == responseBody.contentLength()
        ) {
            statusListener.apply(listener).onCompleted?.invoke()
            return@withContext
        }

        var bis: BufferedInputStream? = null
        var randomAccessFile: RandomAccessFile? = null
        try {
            bis = BufferedInputStream(responseBody.byteStream())

            // 目标文件
            val file = File(downloadInfo.apkSavePath, downloadInfo.fileName)
            // 随机文件访问对象, 可以指定写入的位置
            randomAccessFile = RandomAccessFile(file, "rwd")
            if (downloadInfo.startPoint != 0.toLong())
                randomAccessFile.seek(downloadInfo.startPoint)

            // 读取输入流的数据然后写入到文件内
            val readBytes = bis.readBytes()
            randomAccessFile.write(readBytes)

            // 下载完成回调
            statusListener.apply(listener).onCompleted?.invoke()
            // Log.e("download", "success!")

        } catch (e: Exception) {
            e.printStackTrace()
            // 下载出错回调
            statusListener.apply(listener).onFailed?.invoke(e)
        } finally {
            // 收尾工作, 关闭流
            bis?.close()
            randomAccessFile?.close()
        }

    }

    /**  获取文件断点续传的开始位置  **/
    fun getFileStartPoint(filePath: String, fileName: String): Long {
        if (filePath.isEmpty()) return 0

        val file = File(filePath, fileName)
        return if (file.exists().not()) 0
        else file.length()
    }

}

/**  文件保存状态监听器  **/
class StatusListener {

    /**  当下载完成时回调  **/
    var onCompleted: (suspend () -> Unit)? = null

    /**  当出错时回调  **/
    var onFailed: (suspend (e: Exception) -> Unit)? = null

    /**  当下载完成时回调  **/
    infix fun onCompleted(onCompleted: suspend () -> Unit) {
        this.onCompleted = onCompleted
    }

    /**  当出错时回调  **/
    infix fun onFailed(onFailed: suspend (e: Exception) -> Unit) {
        this.onFailed = onFailed
    }

}